package org.jeecg.modules.wms.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.base.controller.JeecgController;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.wms.entity.WmsInboundOrder;
import org.jeecg.modules.wms.entity.WmsInboundOrderDetail;
import org.jeecg.modules.wms.service.IWmsInboundOrderDetailService;
import org.jeecg.modules.wms.service.IWmsInboundOrderService;
import org.jeecg.modules.wms.vo.WmsInboundOrderVO;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.jeecg.common.system.vo.LoginUser;
import org.springframework.web.servlet.ModelAndView;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.enmus.ExcelType;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.apache.shiro.SecurityUtils;

import java.util.Date;

/**
 * 入库单管理控制器
 */
@Slf4j
@Api(tags = "入库单管理")
@RestController
@RequestMapping("/wms/inboundOrder")
public class WmsInboundOrderController extends JeecgController<WmsInboundOrder, IWmsInboundOrderService> {

    @Autowired
    private IWmsInboundOrderService wmsInboundOrderService;

    @Autowired
    private IWmsInboundOrderDetailService wmsInboundOrderDetailService;

    @Value("${jeecg.path.upload}")
    private String upLoadPath;

    /**
     * 分页列表查询
     */
    @AutoLog(value = "入库单管理-分页列表查询")
    @ApiOperation(value = "入库单管理-分页列表查询", notes = "入库单管理-分页列表查询")
    @GetMapping(value = "/list")
    public Result<IPage<WmsInboundOrderVO>> queryPageList(
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
            HttpServletRequest req) {

        Map<String, Object> params = new HashMap<>();
        // 获取查询参数
        String inboundNo = req.getParameter("inboundNo");
        if (StringUtils.isNotBlank(inboundNo)) {
            params.put("inboundNo", inboundNo);
        }

        String materialCode = req.getParameter("materialCode");
        if (StringUtils.isNotBlank(materialCode)) {
            params.put("materialCode", materialCode);
        }

        String materialName = req.getParameter("materialName");
        if (StringUtils.isNotBlank(materialName)) {
            params.put("materialName", materialName);
        }

        String materialType = req.getParameter("materialType");
        if (StringUtils.isNotBlank(materialType)) {
            params.put("materialType", Integer.parseInt(materialType));
        }

        String businessType = req.getParameter("businessType");
        if (StringUtils.isNotBlank(businessType)) {
            params.put("businessType", Integer.parseInt(businessType));
        }

        String businessNo = req.getParameter("businessNo");
        if (StringUtils.isNotBlank(businessNo)) {
            params.put("businessNo", businessNo);
        }

        String planWarehouseId = req.getParameter("planWarehouseId");
        if (StringUtils.isNotBlank(planWarehouseId)) {
            params.put("planWarehouseId", planWarehouseId);
        }

        String planLocationId = req.getParameter("planLocationId");
        if (StringUtils.isNotBlank(planLocationId)) {
            params.put("planLocationId", planLocationId);
        }

        String actualWarehouseId = req.getParameter("actualWarehouseId");
        if (StringUtils.isNotBlank(actualWarehouseId)) {
            params.put("actualWarehouseId", actualWarehouseId);
        }

        String actualLocationId = req.getParameter("actualLocationId");
        if (StringUtils.isNotBlank(actualLocationId)) {
            params.put("actualLocationId", actualLocationId);
        }

        String status = req.getParameter("status");
        if (StringUtils.isNotBlank(status)) {
            params.put("status", Integer.parseInt(status));
        }

        String batchNo = req.getParameter("batchNo");
        if (StringUtils.isNotBlank(batchNo)) {
            params.put("batchNo", batchNo);
        }

        String supplier = req.getParameter("supplier");
        if (StringUtils.isNotBlank(supplier)) {
            params.put("supplier", supplier);
        }

        // 处理计划入库时间查询（单日期）
        String planInboundTime = req.getParameter("planInboundTime");
        if (StringUtils.isNotBlank(planInboundTime)) {
            params.put("planInboundTime", planInboundTime);
        }

        // 处理实际入库时间查询（单日期）
        String actualInboundTime = req.getParameter("actualInboundTime");
        if (StringUtils.isNotBlank(actualInboundTime)) {
            params.put("actualInboundTime", actualInboundTime);
        }

        String isSurplus = req.getParameter("isSurplus");
        if (StringUtils.isNotBlank(isSurplus)) {
            params.put("isSurplus", Boolean.parseBoolean(isSurplus));
        }

        // 处理订单ID查询
        String productionOrderId = req.getParameter("productionOrderId");
        if (StringUtils.isNotBlank(productionOrderId)) {
            params.put("productionOrderId", productionOrderId);
        }

        // 处理订单编号查询
        String productionOrderNo = req.getParameter("productionOrderNo");
        if (StringUtils.isNotBlank(productionOrderNo)) {
            params.put("productionOrderNo", productionOrderNo);
        }

        Page<WmsInboundOrderVO> page = new Page<>(pageNo, pageSize);
        IPage<WmsInboundOrderVO> pageList = wmsInboundOrderService.queryInboundOrderPageList(page, params);
        return Result.OK(pageList);
    }

    /**
     * 添加
     */
    @AutoLog(value = "入库单管理-添加")
    @ApiOperation(value = "入库单管理-添加", notes = "入库单管理-添加")
    @PostMapping(value = "/add")
    public Result<String> add(@RequestBody WmsInboundOrderVO wmsInboundOrder) {
        try {
            String inboundNo = wmsInboundOrderService.createInboundOrder(wmsInboundOrder);
            log.info("入库单创建成功，单号: {}", inboundNo);
            return Result.OK("添加成功", inboundNo);
        } catch (Exception e) {
            log.error("创建入库单失败", e);
            return Result.error("创建入库单失败: " + e.getMessage());
        }
    }

    /**
     * 添加余料入库单
     */
    @AutoLog(value = "入库单管理-添加余料入库单")
    @ApiOperation(value = "入库单管理-添加余料入库单", notes = "入库单管理-添加余料入库单")
    @PostMapping(value = "/addSurplus")
    public Result<String> addSurplus(@RequestBody WmsInboundOrderVO wmsInboundOrder) {
        try {
            String inboundNo = wmsInboundOrderService.createSurplusInboundOrder(wmsInboundOrder);
            log.info("余料入库单创建成功，单号: {}", inboundNo);
            return Result.OK("添加成功", inboundNo);
        } catch (Exception e) {
            log.error("创建余料入库单失败", e);
            return Result.error("创建余料入库单失败: " + e.getMessage());
        }
    }

    /**
     * 编辑
     */
    @AutoLog(value = "入库单管理-编辑")
    @ApiOperation(value = "入库单管理-编辑", notes = "入库单管理-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody WmsInboundOrderVO wmsInboundOrder) {
        try {
            boolean success = wmsInboundOrderService.updateInboundOrder(wmsInboundOrder);
            if (success) {
                return Result.OK("编辑成功!");
            } else {
                return Result.error("编辑失败!");
            }
        } catch (Exception e) {
            log.error("编辑入库单失败", e);
            return Result.error("编辑入库单失败: " + e.getMessage());
        }
    }

    /**
     * 通过id删除
     */
    @AutoLog(value = "入库单管理-通过id删除")
    @ApiOperation(value = "入库单管理-通过id删除", notes = "入库单管理-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        wmsInboundOrderService.removeById(id);
        //删除详情
        wmsInboundOrderDetailService.remove(new QueryWrapper<WmsInboundOrderDetail>()
                .eq("inbound_order_id", id));
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     */
    @AutoLog(value = "入库单管理-批量删除")
    @ApiOperation(value = "入库单管理-批量删除", notes = "入库单管理-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.wmsInboundOrderService.removeByIds(Arrays.asList(ids.split(",")));
        wmsInboundOrderDetailService.remove(new QueryWrapper<WmsInboundOrderDetail>()
                .in("inbound_order_id", ids));
        return Result.OK("批量删除成功!");
    }

    /**
     * 通过id查询
     */
    @AutoLog(value = "入库单管理-通过id查询")
    @ApiOperation(value = "入库单管理-通过id查询", notes = "入库单管理-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<WmsInboundOrderVO> queryById(@RequestParam(name = "id", required = true) String id) {
        WmsInboundOrderVO wmsInboundOrderVO = wmsInboundOrderService.getInboundOrderById(id);
        if (wmsInboundOrderVO == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(wmsInboundOrderVO);
    }

    /**
     * 查询入库单明细列表
     */
    @AutoLog(value = "入库单管理-查询入库单明细列表")
    @ApiOperation(value = "入库单管理-查询入库单明细列表", notes = "入库单管理-查询入库单明细列表")
    @GetMapping(value = "/queryDetailList")
    public Result<List<WmsInboundOrderDetail>> queryDetailList(
            @RequestParam(name = "inboundOrderId", required = true) String inboundOrderId,
            @RequestParam(name = "showOnlyNotInbound", required = false, defaultValue = "false") Boolean showOnlyNotInbound,
            @RequestParam(name = "excludeFullLocation", required = false, defaultValue = "false") Boolean excludeFullLocation) {

        List<WmsInboundOrderDetail> detailList = wmsInboundOrderService.getDetailsByInboundOrderId(inboundOrderId);

        // 过滤条件
        if ((showOnlyNotInbound != null && showOnlyNotInbound) ||
                (excludeFullLocation != null && excludeFullLocation)) {

            detailList = detailList.stream()
                    .filter(detail -> {
                        boolean keep = true;

                        // 过滤已入库的明细（实际数量等于或大于计划数量）
                        if (showOnlyNotInbound != null && showOnlyNotInbound) {
                            BigDecimal actualQty = detail.getActualQuantity() != null ? detail.getActualQuantity() : BigDecimal.ZERO;
                            BigDecimal planQty = detail.getPlanQuantity() != null ? detail.getPlanQuantity() : BigDecimal.ZERO;
                            keep = keep && (actualQty.compareTo(planQty) < 0);
                        }

                        // 过滤库位状态为已满(5)的明细
                        if (excludeFullLocation != null && excludeFullLocation) {
                            String locationStatus = detail.getLocationStatus();
                            keep = keep && (!"5".equals(locationStatus));
                        }

                        return keep;
                    })
                    .collect(Collectors.toList());
        }

        return Result.OK(detailList);
    }

    /**
     * 确认入库
     */
    @AutoLog(value = "入库单管理-确认入库")
    @ApiOperation(value = "入库单管理-确认入库", notes = "入库单管理-确认入库")
    @PostMapping(value = "/confirmInbound")
    public Result<?> confirmInbound(
            @RequestParam(name = "id", required = true) String id,
            @RequestParam(name = "detailId", required = true) String detailId,
            @RequestParam(name = "actualWarehouseId", required = true) String actualWarehouseId,
            @RequestParam(name = "actualLocationId", required = true) String actualLocationId,
            @RequestParam(name = "actualQuantity", required = true) BigDecimal actualQuantity,
            @RequestParam(name = "remark", required = false) String remark) {

        try {
            boolean success = wmsInboundOrderService.confirmInbound(id, detailId, actualWarehouseId, actualLocationId, actualQuantity, remark);
            if (success) {
                return Result.OK("确认入库成功!");
            } else {
                return Result.error("确认入库失败!");
            }
        } catch (Exception e) {
            log.error("确认入库失败", e);
            return Result.error("确认入库失败: " + e.getMessage());
        }
    }

    /**
     * 取消入库单
     */
    @AutoLog(value = "入库单管理-取消入库单")
    @ApiOperation(value = "入库单管理-取消入库单", notes = "入库单管理-取消入库单")
    @PostMapping(value = "/cancelInboundOrder")
    public Result<?> cancelInboundOrder(
            @RequestParam(name = "id", required = true) String id,
            @RequestParam(name = "remark", required = false) String remark) {

        try {
            boolean success = wmsInboundOrderService.cancelInboundOrder(id, remark);
            if (success) {
                return Result.OK("取消入库单成功!");
            } else {
                return Result.error("取消入库单失败!");
            }
        } catch (Exception e) {
            log.error("取消入库单失败", e);
            return Result.error("取消入库单失败: " + e.getMessage());
        }
    }

    /**
     * 更新入库单明细
     */
    @AutoLog(value = "入库单管理-更新入库单明细")
    @ApiOperation(value = "入库单管理-更新入库单明细", notes = "入库单管理-更新入库单明细")
    @PostMapping(value = "/updateDetail")
    public Result<?> updateDetail(@RequestBody WmsInboundOrderDetail detail) {
        try {
            // 获取是否需要更新库存的标记
            Boolean updateInventory = detail.getUpdateInventory() != null ? detail.getUpdateInventory() : false;

            // 调用服务层方法，在一个事务中完成所有操作
            boolean success = wmsInboundOrderService.updateDetailWithLocationStatus(detail, updateInventory);

            if (success) {
                return Result.OK("更新明细成功!");
            } else {
                return Result.error("更新明细失败!");
            }
        } catch (Exception e) {
            log.error("更新入库单明细失败", e);
            return Result.error("更新入库单明细失败: " + e.getMessage());
        }
    }

    /**
     * 添加额外库位明细
     */
    @AutoLog(value = "入库单管理-添加额外库位明细")
    @ApiOperation(value = "入库单管理-添加额外库位明细", notes = "入库单管理-添加额外库位明细")
    @PostMapping(value = "/addExtraLocationDetail")
    public Result<?> addExtraLocationDetail(@RequestBody WmsInboundOrderDetail detail) {
        try {
            // 设置为额外库位明细
            detail.setIsExtra(true);

            // 生成新ID
            detail.setId(null);

            // 获取是否需要更新库存的标记
            Boolean updateInventory = detail.getUpdateInventory() != null ? detail.getUpdateInventory() : false;

            // 在一个事务中保存明细并处理仓库和库位名称
            boolean success = wmsInboundOrderService.saveExtraLocationDetail(detail, updateInventory);

            if (success) {
                return Result.OK("添加额外库位成功!");
            } else {
                return Result.error("添加额外库位失败!");
            }
        } catch (Exception e) {
            log.error("添加额外库位明细失败", e);
            return Result.error("添加额外库位明细失败: " + e.getMessage());
        }
    }

    /**
     * 批量确认入库 - 接收请求体中的参数
     * 兼容前端不同的请求方式
     */
    @AutoLog(value = "入库单管理-批量确认入库(请求体)")
    @ApiOperation(value = "入库单管理-批量确认入库(请求体)", notes = "入库单管理-批量确认入库(请求体)")
    @PostMapping(value = "/batchConfirmInboundWithBody")
    public Result<?> batchConfirmInboundWithBody(@RequestBody Map<String, Object> params, HttpServletRequest request) {
        try {
            String inboundOrderId = (String) params.get("inboundOrderId");
            if (inboundOrderId == null || inboundOrderId.trim().isEmpty()) {
                return Result.error("入库单ID不能为空");
            }

            @SuppressWarnings("unchecked")
            List<Map<String, Object>> details = (List<Map<String, Object>>) params.get("details");
            if (details == null || details.isEmpty()) {
                return Result.error("明细列表不能为空");
            }

            log.info("批量确认入库(请求体)，入库单ID: {}, 明细数量: {}", inboundOrderId, details.size());

            // 获取当前操作人信息
            String operator = null;
            String operatorId = null;
            try {
                // 获取当前登录用户
                LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
                if (sysUser != null) {
                    operator = sysUser.getRealname();
                    operatorId = sysUser.getId();
                    // 将操作人信息添加到请求参数中
                    params.put("operator", operator);
                }
            } catch (Exception e) {
                log.warn("获取当前登录用户信息失败", e);
            }

            // 添加操作时间
            params.put("operateTime", new Date());

            // 设置是否更新成本的标志
            // 遍历明细，检查是否有单位成本信息
            boolean updateCost = false;
            for (Map<String, Object> detail : details) {
                if (detail.containsKey("unitCost") && detail.get("unitCost") != null) {
                    // 如果有单位成本且不为null，则需要更新成本信息
                    Object unitCost = detail.get("unitCost");
                    if (unitCost instanceof BigDecimal && ((BigDecimal) unitCost).compareTo(BigDecimal.ZERO) > 0) {
                        updateCost = true;
                        break;
                    } else if (unitCost instanceof Number && ((Number) unitCost).doubleValue() > 0) {
                        updateCost = true;
                        break;
                    } else if (unitCost instanceof String && !((String) unitCost).trim().isEmpty()) {
                        try {
                            if (Double.parseDouble((String) unitCost) > 0) {
                                updateCost = true;
                                break;
                            }
                        } catch (NumberFormatException e) {
                            // 忽略非数字字符串
                        }
                    }
                }
            }

            // 将是否更新成本的标志添加到请求参数中
            params.put("updateCost", updateCost);

            log.info("批量确认入库，更新成本标志: {}, 操作人: {}", updateCost, operator);

            boolean success = wmsInboundOrderService.batchConfirmInboundWithHistory(inboundOrderId, details, params);
            if (success) {
                // 入库成功后，触发出库明细重新分配  更新操作人信息
                WmsInboundOrder inboundOrder = wmsInboundOrderService.getById(inboundOrderId);
                if (inboundOrder != null) {
                    if (oConvertUtils.isNotEmpty(inboundOrder.getOperatorIds())) {
                        if (!inboundOrder.getOperatorIds().contains(operatorId)) {
                            inboundOrder.setOperatorIds(inboundOrder.getOperatorIds() + "," + operatorId);
                        }
                    } else {
                        inboundOrder.setOperatorIds(operatorId);
                    }
                    if (oConvertUtils.isNotEmpty(inboundOrder.getOperatorNames())) {
                        if (!inboundOrder.getOperatorNames().contains(operator)) {
                            inboundOrder.setOperatorNames(inboundOrder.getOperatorNames() + "," + operator);
                        }
                    } else {
                        inboundOrder.setOperatorNames(operator);
                    }
                    wmsInboundOrderService.updateById(inboundOrder);
                }
                try {
                    wmsInboundOrderService.triggerOutboundReallocationAfterInbound(details);
                    log.info("入库成功后出库明细重新分配触发完成");
                } catch (Exception e) {
                    log.warn("入库成功后出库明细重新分配失败，但不影响入库结果", e);
                }
                return Result.OK("批量确认入库成功!");
            } else {
                return Result.error("批量确认入库失败!");
            }
        } catch (Exception e) {
            log.error("批量确认入库失败", e);
            return Result.error("批量确认入库失败: " + e.getMessage());
        }
    }

    /**
     * 更新入库单基本信息
     */
    @AutoLog(value = "入库单管理-更新入库单基本信息")
    @ApiOperation(value = "入库单管理-更新入库单基本信息", notes = "入库单管理-更新入库单基本信息")
    @PostMapping(value = "/updateBasicInfo")
    public Result<?> updateBasicInfo(@RequestBody WmsInboundOrder inboundOrder) {
        try {
            // 只更新特定字段
            WmsInboundOrder existingOrder = wmsInboundOrderService.getById(inboundOrder.getId());
            if (existingOrder == null) {
                return Result.error("未找到对应的入库单");
            }

            // 更新实际入库时间
            if (inboundOrder.getActualInboundTime() != null) {
                existingOrder.setActualInboundTime(inboundOrder.getActualInboundTime());
            }

            // 更新总实际入库数量
            if (inboundOrder.getTotalActualQuantity() != null) {
                existingOrder.setTotalActualQuantity(inboundOrder.getTotalActualQuantity());
            }

            // 更新入库凭证
            if (inboundOrder.getInboundVoucher() != null) {
                existingOrder.setInboundVoucher(inboundOrder.getInboundVoucher());
            }

            // 保存更新
            boolean success = wmsInboundOrderService.updateById(existingOrder);
            if (success) {
                return Result.OK("更新入库单基本信息成功!");
            } else {
                return Result.error("更新入库单基本信息失败!");
            }
        } catch (Exception e) {
            log.error("更新入库单基本信息失败", e);
            return Result.error("更新入库单基本信息失败: " + e.getMessage());
        }
    }

    /**
     * 移动端入库单查询接口 - 支持折叠显示和模糊搜索
     */
    @AutoLog(value = "入库单管理-移动端查询")
    @ApiOperation(value = "入库单管理-移动端查询", notes = "入库单管理-移动端查询，支持折叠显示和模糊搜索")
    @GetMapping(value = "/queryForMobile")
    public Result<IPage<WmsInboundOrderVO>> queryForMobile(
            @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
            @RequestParam(name = "pageSize", defaultValue = "20") Integer pageSize,
            @RequestParam(name = "searchKeyword", required = false) String searchKeyword,
            @RequestParam(name = "orderTypes", required = false) String orderTypes,
            @RequestParam(name = "orderStatus", required = false) String orderStatus,
            @RequestParam(name = "orderNo", required = false) String orderNo,
            @RequestParam(name = "supplierName", required = false) String supplierName,
            @RequestParam(name = "warehouseName", required = false) String warehouseName,
            @RequestParam(name = "createBy", required = false) String createBy,
            HttpServletRequest req) {

        log.info("移动端入库单查询，页码: {}, 页大小: {}, 搜索关键词: {}, 入库类型: {}, 订单状态: {}, 入库单号: {}, 供应商名称: {}, 仓库名称: {}, 创建人: {}",
                pageNo, pageSize, searchKeyword, orderTypes, orderStatus, orderNo, supplierName, warehouseName, createBy);

        try {
            Map<String, Object> query = new HashMap<>();

            // 模糊搜索关键词 - 支持入库单号、供应商名称、仓库名称、创建人等字段
            if (StringUtils.isNotBlank(searchKeyword)) {
                query.put("searchKeyword", searchKeyword.trim());
            }

            // 具体字段模糊查询
            if (StringUtils.isNotBlank(orderNo)) {
                query.put("orderNo", orderNo.trim());
            }
            if (StringUtils.isNotBlank(supplierName)) {
                query.put("supplierName", supplierName.trim());
            }
            if (StringUtils.isNotBlank(warehouseName)) {
                query.put("warehouseName", warehouseName.trim());
            }
            if (StringUtils.isNotBlank(createBy)) {
                query.put("createBy", createBy.trim());
            }

            // 业务类型筛选 - 支持单个或多个类型
            if (StringUtils.isNotBlank(orderTypes)) {
                String[] typeArray = orderTypes.split(",");
                List<String> typeList = new ArrayList<>();
                for (String type : typeArray) {
                    String trimmedType = type.trim();
                    if (StringUtils.isNotBlank(trimmedType) && !"all".equals(trimmedType)) {
                        typeList.add(trimmedType);
                    }
                }
                if (!typeList.isEmpty()) {
                    query.put("orderTypes", typeList);
                }
            }

            // 订单状态筛选
            if (StringUtils.isNotBlank(orderStatus) && !"all".equals(orderStatus.trim()) && orderStatus != null) {
                query.put("orderStatus", orderStatus.trim());
            }

            Page<WmsInboundOrderVO> page = new Page<>(pageNo, pageSize);
            IPage<WmsInboundOrderVO> pageList = wmsInboundOrderService.queryInboundOrderForMobile(page, query);

            log.info("移动端入库单查询完成，返回 {} 条记录", pageList.getRecords().size());
            return Result.OK(pageList);

        } catch (Exception e) {
            log.error("移动端入库单查询失败", e);
            return Result.error("查询失败: " + e.getMessage());
        }
    }

    /**
     * 移动端查询入库单明细列表 - 优化版本
     */
    @AutoLog(value = "入库单管理-移动端查询明细列表")
    @ApiOperation(value = "入库单管理-移动端查询明细列表", notes = "入库单管理-移动端查询明细列表，返回完整明细信息")
    @GetMapping(value = "/queryDetailListForMobile")
    public Result<List<WmsInboundOrderDetail>> queryDetailListForMobile(
            @RequestParam(name = "inboundOrderId", required = true) String inboundOrderId) {

        try {
            log.info("移动端查询入库单明细，入库单ID: {}", inboundOrderId);

            List<WmsInboundOrderDetail> detailList = wmsInboundOrderService.getDetailsByInboundOrderId(inboundOrderId);

            log.info("移动端查询入库单明细完成，返回 {} 条明细记录", detailList.size());
            return Result.OK(detailList);

        } catch (Exception e) {
            log.error("移动端查询入库单明细失败，入库单ID: {}", inboundOrderId, e);
            return Result.error("查询明细失败: " + e.getMessage());
        }
    }

    /**
     * 查询当前用户操作的入库单记录
     *
     * @param pageNo   页码
     * @param pageSize 每页条数
     * @return 操作记录列表
     */
    @AutoLog(value = "入库单管理-查询用户操作记录")
    @ApiOperation(value = "入库单管理-查询用户操作记录", notes = "入库单管理-查询用户操作记录")
    @GetMapping(value = "/getUserOperationRecords")
    public Result<?> getUserOperationRecords(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                             @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                             @RequestParam(name = "inboundNo", required = false) String inboundNo,
                                             @RequestParam(name = "status", required = false) String status,
                                             @RequestParam(name = "businessType", required = false) String businessType,
                                             @RequestParam(name = "planInboundStartTime", required = false) String planInboundStartTime,
                                             @RequestParam(name = "planInboundEndTime", required = false) String planInboundEndTime,
                                             @RequestParam(name = "actualInboundStartTime", required = false) String actualInboundStartTime,
                                             @RequestParam(name = "actualInboundEndTime", required = false) String actualInboundEndTime,
                                             @RequestParam(name = "warehouseName", required = false) String warehouseName,
                                             @RequestParam(name = "locationName", required = false) String locationName,
                                             @RequestParam(name = "materialCode", required = false) String materialCode,
                                             @RequestParam(name = "materialName", required = false) String materialName) {
        try {
            Page<WmsInboundOrderVO> page = new Page<>(pageNo, pageSize);

            // 构建查询条件
            WmsInboundOrder queryParam = new WmsInboundOrder();
            if (StringUtils.isNotBlank(inboundNo)) {
                queryParam.setInboundNo(inboundNo);
            }

            IPage<WmsInboundOrderVO> pageList = wmsInboundOrderService.getUserOperationRecords(page, queryParam,
                    planInboundStartTime, planInboundEndTime, actualInboundStartTime, actualInboundEndTime,
                    warehouseName, locationName, materialCode, materialName,
                    (StringUtils.isNotBlank(status) ? Arrays.asList(status.split(",")) : null),
                    (StringUtils.isNotBlank(businessType) ? Arrays.asList(businessType.split(",")) : null));
            return Result.OK(pageList);
        } catch (Exception e) {
            log.error("查询用户入库操作记录失败", e);
            return Result.error("查询操作记录失败：" + e.getMessage());
        }
    }

    /**
     * 获取物料业务统计信息
     */
    @ApiOperation(value = "获取物料业务统计信息", notes = "获取物料入库单和出库单总数统计")
    @GetMapping(value = "/statistics/business")
    public Result<java.util.Map<String, Object>> getMaterialBusinessStatistics() {
        try {
            java.util.Map<String, Object> statistics = new java.util.HashMap<>();

            // 获取物料入库单总数
            Long inboundCount = wmsInboundOrderService.getMaterialInboundOrderCount();
            statistics.put("materialInboundCount", inboundCount != null ? inboundCount : 0);

            // 获取物料出库单总数  
            Long outboundCount = wmsInboundOrderService.getMaterialOutboundOrderCount();
            statistics.put("materialOutboundCount", outboundCount != null ? outboundCount : 0);

            return Result.OK(statistics);
        } catch (Exception e) {
            log.error("获取物料业务统计信息失败", e);
            return Result.error("获取物料业务统计信息失败：" + e.getMessage());
        }
    }

    /**
     * 解析余料入库单Excel文件
     */
    @AutoLog(value = "入库单管理-解析余料入库单Excel文件")
    @ApiOperation(value = "入库单管理-解析余料入库单Excel文件", notes = "解析上传的Excel文件，提取余料入库单数据")
    @PostMapping(value = "/parseRemainingMaterialFile")
    public Result<List<Map<String, Object>>> parseRemainingMaterialFile(@RequestParam("file") MultipartFile file) {
        try {
            log.info("开始解析余料入库单Excel文件，文件名: {}", file.getOriginalFilename());

            if (file.isEmpty()) {
                return Result.error("上传文件为空");
            }

            // 检查文件类型
            String fileName = file.getOriginalFilename();
            if (fileName == null || (!fileName.endsWith(".xlsx") && !fileName.endsWith(".xls"))) {
                return Result.error("文件格式不正确，请上传Excel文件");
            }

            // 调用服务层解析Excel文件
            List<Map<String, Object>> parsedData = wmsInboundOrderService.parseRemainingMaterialExcel(file);

            log.info("Excel文件解析完成，共解析出 {} 条数据", parsedData.size());
            return Result.OK(parsedData);

        } catch (Exception e) {
            log.error("解析余料入库单Excel文件失败", e);
            return Result.error("文件解析失败: " + e.getMessage());
        }
    }

    /**
     * 保存余料入库单导入数据
     */
    @AutoLog(value = "入库单管理-保存余料入库单导入数据")
    @ApiOperation(value = "入库单管理-保存余料入库单导入数据", notes = "保存从Excel导入的余料入库单数据")
    @PostMapping(value = "/saveRemainingMaterialInbound")
    public Result<?> saveRemainingMaterialInbound(@RequestBody Map<String, Object> params) {
        try {
            List<Map<String, Object>> dataList = (List<Map<String, Object>>) params.get("dataList");
            if (dataList == null || dataList.isEmpty()) {
                return Result.error("导入数据不能为空");
            }

            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            String createBy = sysUser.getUsername();
            String createByName = sysUser.getRealname();

            boolean success = wmsInboundOrderService.saveRemainingMaterialInboundFromImport(dataList, createBy, createByName);

            if (success) {
                return Result.ok("导入成功");
            } else {
                return Result.error("导入失败");
            }
        } catch (Exception e) {
            log.error("保存余料入库单导入数据失败", e);
            return Result.error("导入失败: " + e.getMessage());
        }
    }

    /**
     * 一键入库（余料入库单）
     */
    @PostMapping(value = "/oneClickInbound")
    @AutoLog(value = "入库单-一键入库")
    public Result<?> oneClickInbound(@RequestParam(name = "id") String id) {
        try {
            if (oConvertUtils.isEmpty(id)) {
                return Result.error("入库单ID不能为空");
            }

            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

            boolean success = wmsInboundOrderService.oneClickInbound(id, sysUser.getRealname());

            if (success) {
                return Result.ok("一键入库成功");
            } else {
                return Result.error("一键入库失败");
            }
        } catch (Exception e) {
            log.error("一键入库失败", e);
            return Result.error("一键入库失败: " + e.getMessage());
        }
    }
}